package com.kelvem.saas.workbanch.security.shiro;

import com.kelvem.saas.workbanch.core.exception.ErrorCodeEnum;
import com.kelvem.saas.workbanch.core.exception.SaasException;
import com.kelvem.saas.workbanch.core.utils.ServletUtils;
import com.kelvem.saas.workbanch.core.system.model.SysUserEntity;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.security.SignatureException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.BearerToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.context.annotation.Lazy;

import java.util.HashSet;
import java.util.Set;

@Slf4j
public class JwtRealm extends AuthorizingRealm {

    @Lazy
    @Resource
    private ShiroUserService shiroUserService;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof BearerToken;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SysUserEntity sysUser = (SysUserEntity) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

//        Set<String> roleSet = new HashSet<>();
//        roleSet.add(sysUser.getOrgId().toString());
//        roleSet.add("default"); // 已登录的默认权限
//        if ("admin".equals(sysUser.getUsername())) {
//            roleSet.add("admin"); // admin权限
//        }
//        authorizationInfo.setRoles(roleSet);

        Set<String> permissionSet = shiroUserService.filterOrgUrlByOrgId(sysUser.getOrgId());
        authorizationInfo.setStringPermissions(permissionSet);

        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        BearerToken jwtToken = (BearerToken) token;
        String jwt = (String)jwtToken.getPrincipal();
        if (jwt == null) {
            log.warn("缺少身份认证信息, IP地址:  "+ ServletUtils.getClientIP() +",URL:" + ServletUtils.getRequestURI());
            throw new SaasException(ErrorCodeEnum.JWT_NOTOKEN);
        }

        try {
            SysUserEntity sysUser = JwtUtil.extractUser(jwt);

            // Object principal, Object credentials, String realmName
            return new SimpleAuthenticationInfo(sysUser, jwt, getName());

        } catch (ExpiredJwtException e) {
            log.info("JWT token is expired");
            throw new SaasException(ErrorCodeEnum.JWT_EXPIRED, e);
        } catch (IllegalArgumentException e) {
            log.warn("身份信息解析失败, IP地址:  "+ ServletUtils.getClientIP() +",URL:" + ServletUtils.getRequestURI());
            throw new SaasException(ErrorCodeEnum.JWT_MALFORMED, e);
        } catch (SignatureException e) {
            log.warn("JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.");
            log.warn("signature错误, IP地址:  "+ ServletUtils.getClientIP() +",URL:" + ServletUtils.getRequestURI());
            throw new SaasException(ErrorCodeEnum.JWT_SIGN_ERR, e);
        } catch (Exception e) {
            log.warn("JWT错误, IP地址:  "+ ServletUtils.getClientIP() +",URL:" + ServletUtils.getRequestURI());
            throw new SaasException(ErrorCodeEnum.JWT_INVALID, e);
        }
    }
}

